﻿using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace InputKeyboard
{
    public class User32
    {
        #region 键盘操作
        public const byte Keyevent_KeyDown = 0x00;
        public const byte Keyevent_KeyUp = 0x02;

        /// <summary>
        /// 键盘事件
        /// </summary>
        /// <param name="bVk"></param>
        /// <param name="bScan"></param>
        /// <param name="dwFlags"></param>
        /// <param name="dwExtraInfo"></param>
        [DllImport("user32")]
        public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
        /// <summary>
        /// 获取当前键盘CapsLok状态
        /// </summary>
        /// <param name="keyCode"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
        public static extern short GetKeyState(int keyCode);

        [DllImport("user32.dll")]
        public static extern int MapVirtualKey(uint uCode, uint uMapType);
        /// <summary>
        /// 键盘按下
        /// </summary>
        /// <param name="key"></param>
        public static void KeyDown(byte key)
        {
            keybd_event(key, Convert.ToByte(MapVirtualKey(key, 0)), Keyevent_KeyDown, 0);
        }
        /// <summary>
        /// 键盘抬起
        /// </summary>
        /// <param name="key"></param>
        public static void KeyUp(byte key)
        {
            keybd_event(key, Convert.ToByte(MapVirtualKey(key, 0)), Keyevent_KeyUp, 0);
        }
        /// <summary>
        /// 获取CapsLock键状态
        /// </summary>
        /// <returns></returns>
        public static bool GetCapsLockState()
        {
            return (((ushort)GetKeyState(20)) & 0xffff) != 0;
        }
        /// <summary>
        /// 数字键是否按下状态
        /// </summary>
        /// <returns></returns>
        public static bool GetNumberState()
        {
            return (((ushort)GetKeyState(144)) & 0xffff) != 0;
        }

        #region 键值
        public const byte Key_Backspace = 8;
        public const byte Key_Tab = 9;
        public const byte Key_Clear = 12;
        public const byte Key_Enter = 13;
        public const byte Key_Shift = 16;
        public const byte Key_Control = 17;
        public const byte Key_Alt = 18;
        public const byte Key_CapsLock = 20;
        public const byte Key_Esc = 27;
        public const byte Key_Spacebar = 32;
        public const byte Key_PageUp = 33;
        public const byte Key_PageDown = 34;
        public const byte Key_End = 35;
        public const byte Key_Home = 36;
        public const byte Key_Left = 37;
        public const byte Key_Up = 38;
        public const byte Key_Right = 39;
        public const byte Key_Down = 40;
        public const byte Key_Insert = 45;
        public const byte Key_Delete = 46;

        public const byte Key_0 = 48;
        public const byte Key_1 = 49;
        public const byte Key_2 = 50;
        public const byte Key_3 = 51;
        public const byte Key_4 = 52;
        public const byte Key_5 = 53;
        public const byte Key_6 = 54;
        public const byte Key_7 = 55;
        public const byte Key_8 = 56;
        public const byte Key_9 = 57;

        public const byte Key_A = 65;
        public const byte Key_B = 66;
        public const byte Key_C = 67;
        public const byte Key_D = 68;
        public const byte Key_E = 69;
        public const byte Key_F = 70;
        public const byte Key_G = 71;
        public const byte Key_H = 72;
        public const byte Key_I = 73;
        public const byte Key_J = 74;
        public const byte Key_K = 75;
        public const byte Key_L = 76;
        public const byte Key_M = 77;
        public const byte Key_N = 78;
        public const byte Key_O = 79;
        public const byte Key_P = 80;
        public const byte Key_Q = 81;
        public const byte Key_R = 82;
        public const byte Key_S = 83;
        public const byte Key_T = 84;
        public const byte Key_U = 85;
        public const byte Key_V = 86;
        public const byte Key_W = 87;
        public const byte Key_X = 88;
        public const byte Key_Y = 89;
        public const byte Key_Z = 90;

        public const byte Key_Win = 91;

        public const byte Key_N0 = 96;
        public const byte Key_N1 = 97;
        public const byte Key_N2 = 98;
        public const byte Key_N3 = 99;
        public const byte Key_N4 = 100;
        public const byte Key_N5 = 101;
        public const byte Key_N6 = 102;
        public const byte Key_N7 = 103;
        public const byte Key_N8 = 104;
        public const byte Key_N9 = 105;
        public const byte Key_NMultiply = 106;// *
        public const byte Key_NAdd = 107;// +
        public const byte Key_NEnter = 108;
        public const byte Key_NSubtract = 109;// -
        public const byte Key_NPoint = 110;// .
        public const byte Key_NDivide = 111;// /

        public const byte Key_F1 = 112;
        public const byte Key_F2 = 113;
        public const byte Key_F3 = 114;
        public const byte Key_F4 = 115;
        public const byte Key_F5 = 116;
        public const byte Key_F6 = 117;
        public const byte Key_F7 = 118;
        public const byte Key_F8 = 119;
        public const byte Key_F9 = 120;
        public const byte Key_F10 = 121;
        public const byte Key_F11 = 122;
        public const byte Key_F12 = 123;

        public const byte Key_NumLock = 144;
        public const byte Key_Semicolon = 186;// ;:
        public const byte Key_Equal = 187;// =+
        public const byte Key_Comma = 188;// ,<
        public const byte Key_Horizontal = 189;// -_
        public const byte Key_Point = 190;// .>
        public const byte Key_Slash = 191;// /?
        public const byte Key_Stop = 192;// `~
        public const byte Key_BracketLeft = 219;// [{
        public const byte Key_Vertical = 220;// \|
        public const byte Key_BracketRight = 221;// ]}
        public const byte Key_Quotes = 222;// '"
        #endregion
        #endregion

        /// <summary>
        /// 获取当前光标在屏幕中的位置
        /// </summary>
        /// <param name="lpPoint"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out POINT lpPoint);

        /// <summary>
        /// 获取当前焦点句柄
        /// </summary>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ResourceExposure(ResourceScope.Machine)]
        public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);

        /// <summary>
        /// 获取输入法列表
        /// </summary>
        /// <param name="size"></param>
        /// <param name="hkls"></param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern int GetKeyboardLayoutList(int size, [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] hkls);
        /// <summary>
        /// 查询当前使用的输入法
        /// </summary>
        /// <param name="dwLayout"></param>
        /// <returns></returns>
        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetKeyboardLayout(int dwLayout);
        /// <summary>
        /// 设置输入法
        /// </summary>
        /// <param name="hkl"></param>
        /// <param name="uFlags"></param>
        /// <returns></returns>
        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern IntPtr ActivateKeyboardLayout(IntPtr hkl, int uFlags);

        #region Native Methods
        public const int WS_EX_NOACTIVATE = 0x08000000;
        public const int GWL_EXSTYLE = -20;

        public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
        {
            return Environment.Is64BitProcess ? GetWindowLong64(hWnd, nIndex) : GetWindowLong32(hWnd, nIndex);
        }

        public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
        {
            return Environment.Is64BitProcess ? SetWindowLong64(hWnd, nIndex, dwNewLong) : SetWindowLong32(hWnd, nIndex, dwNewLong);
        }

        [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
        private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
        private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
        private static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLong64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
        #endregion

        #region 系统菜单
        public const int MF_BYPOSITION = 0x0400;
        public const int MF_DISABLED = 0x0002;

        [DllImport("user32.dll", EntryPoint = "GetSystemMenu")]
        public static extern IntPtr GetSystemMenu(IntPtr hwnd, int revert);
        [DllImport("user32.dll", EntryPoint = "GetMenuItemCount")]
        public static extern int GetMenuItemCount(IntPtr hmenu);
        [DllImport("user32.dll", EntryPoint = "RemoveMenu")]
        public static extern int RemoveMenu(IntPtr hmenu, int npos, int wflags);
        [DllImport("user32.dll", EntryPoint = "DrawMenuBar")]
        public static extern int DrawMenuBar(IntPtr hwnd);
        #endregion
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;
        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }
}
